﻿using Infrastructure.Extension;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Properties;
using System.Text;

namespace System
{
    /// <summary>
    /// 包含了与字符串相关的一些常用扩展方法
    /// </summary>
    [EditorBrowsable(EditorBrowsableState.Never)]
    public static partial class StringExtensions
    {
        #region Set 设置

        /// <summary>
        /// 为字符串设定默认值
        /// </summary>
        /// <param name="source">要设置的值</param>
        /// <param name="defaultValue">如果要设定的值为空，则返回此默认值</param>
        /// <returns>设定后的结果</returns>
        public static string DefaultForEmpty(this string source, string defaultValue)
        {
            return string.IsNullOrEmpty(source) ? defaultValue : source;
        }

        #endregion Set 设置

        #region Boolean 判断

        /// <summary>
        /// 	Determines whether the specified string is null or empty.
        /// </summary>
        /// <param name = "value">The string value to check.</param>
        public static bool IsEmpty(this string value)
        {
            return ((value == null) || (value.Length == 0));
        }

        /// <summary>
        /// 	Determines whether the specified string is not null or empty.
        /// </summary>
        /// <param name = "value">The string value to check.</param>
        public static bool IsNotEmpty(this string value)
        {
            return (value.IsEmpty() == false);
        }

        /// <summary>
        /// 判断字符串是否为NULL或为空
        /// </summary>
        /// <param name="source">字符串</param>
        /// <returns>true表示字符串为NULL或为空</returns>
        public static bool IsNullOrEmpty(this string source)
        {
            return string.IsNullOrEmpty(source);
        }

        /// <summary>
        /// 	Checks whether the string is empty and returns a default value in case.
        /// </summary>
        /// <param name = "value">The string to check.</param>
        /// <param name = "defaultValue">The default value.</param>
        /// <returns>Either the string or the default value.</returns>
        public static string IfEmpty(this string value, string defaultValue)
        {
            return (value.IsNotEmpty() ? value : defaultValue);
        }

        /// <summary>
        /// 返回一个值，该值指示指定的 System.String 对象是否出现在此字符串中。一个参数指定要用于指定字符串的搜索类型。
        /// </summary>
        /// <param name="str">字符串</param>
        /// <param name="key">关键字</param>
        /// <param name="comparison">比较方式</param>
        /// <returns>包含为true， 否则为false</returns>
        public static bool Contains(this string str, string key, StringComparison comparison)
        {
            //str.Contains(key);
            return str.IndexOf(key, comparison) != -1;
        }

        /// <summary>
        /// 获得以指定字符串结尾的字符串
        /// </summary>
        /// <param name="value">字符串</param>
        /// <param name="ending">结尾</param>
        /// <returns></returns>
        public static string EnsureEndWith(this string value, string ending)
        {
            if (value == null || value.EndsWith(ending)) return value;
            return value + ending;
        }

        /// <summary>
        /// 获得以指定字符串开头的字符串
        /// </summary>
        /// <param name="value">字符串</param>
        /// <param name="starting">开头</param>
        /// <returns></returns>
        public static string EnsureStartWith(this string value, string starting)
        {
            if (value == null || value.StartsWith(starting)) return value;
            return starting + value;
        }

        #endregion Boolean 判断

        #region Convert 转换

        #region ToBoolean

        /// <summary>
        /// 转换字符串到可空逻辑值
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public static bool? ToBooleanNullable(this string value)
        {
            if (string.IsNullOrEmpty(value)) return null;

            if (value == "1" || string.Compare("true", value, true) == 0) return true;
            if (value == "0" || string.Compare("false", value, true) == 0) return false;

            return null;
        }

        /// <summary>
        /// 转换字符串到逻辑值
        /// </summary>
        /// <param name="value">要转换的字符串，如果转换失败，则返回 false</param>
        /// <returns>转换后的 <see cref="T:System.Boolean"/></returns>
        public static bool ToBoolean(this string value)
        {
            return ToBoolean(value, false);
        }

        /// <summary>
        /// 转换字符串到逻辑值
        /// </summary>
        /// <param name="value">要转换的字符串</param>
        /// <param name="defaultValue">如果转换失败返回的默认值</param>
        /// <returns>转换后的 <see cref="T:System.Boolean"/></returns>
        public static bool ToBoolean(this string value, bool defaultValue)
        {
            var b = value.ToBooleanNullable();
            return b.HasValue ? b.Value : defaultValue;
        }

        #endregion ToBoolean

        #region ToHexByte

        /// <summary>
        /// 转换为BYTE
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public static byte ToHexByte(this char code)
        {
            if (code >= 'A' && code <= 'F') return (byte)(10 + (code - 'A'));
            if (code >= 'a' && code <= 'f') return (byte)(10 + (code - 'a'));
            if (code >= '0' && code <= '9') return (byte)(code - '0');
            return 0;
        }

        #endregion ToHexByte

        #region ToByte[]

        /// <summary>
        /// 将Base64格式的字符串转换为字节数组
        /// </summary>
        /// <param name="base64String">要转换的Base64字符串</param>
        /// <returns>字节数组</returns>
        public static byte[] ConvertBase64ToBytes(this string base64String)
        {
            if (base64String.IsNullOrEmpty()) return null;

            return Convert.FromBase64String(base64String);
        }

        /// <summary>
        /// 转换为字节数组
        /// </summary>
        /// <param name="value">字符串值</param>
        /// <returns>结果字节数组</returns>
        public static byte[] ToBytes(this string value)
        {
            return ToBytes(value, null);
        }

        /// <summary>
        /// 转换为字节数组
        /// </summary>
        /// <param name="value">字符串值</param>
        /// <param name="encoding">使用的编码</param>
        /// <returns>结果字节数组</returns>
        public static byte[] ToBytes(this string value, Encoding encoding)
        {
            return value.IsNullOrEmpty() ? new byte[] { } : (encoding ?? Encoding.Unicode).GetBytes(value);
        }

        /// <summary>
        /// 将字符串转换为转换为ASCII码
        /// </summary>
        /// <param name="data">字符串</param>
        /// <returns>byte[]</returns>
        public static byte[] ToASCII(this string data)
        {
            byte[] asciiBytes = null;
            if (!string.IsNullOrEmpty(data))
                asciiBytes = Encoding.ASCII.GetBytes(data);
            return asciiBytes;
        }

        #endregion ToByte[]

        #region ToInt32

        /// <summary>
        /// 将字符串转换为Int值，如果转换失败，则返回0
        /// </summary>
        /// <param name="value">字符串</param>
        /// <param name="defaultValue">如果转换失败,则返回的默认值</param>
        /// <returns>转换后的 <see cref="System.Int32"/></returns>
        public static int ToInt32(this string value, int defaultValue = 0, NumberStyles style = NumberStyles.Any, IFormatProvider provider = null)
        {
            int temp;
            return int.TryParse(value, style, provider, out temp) ? temp : defaultValue;
        }

        /// <summary>
        /// 将字符串转换为Int值，如果转换失败，则返回null
        /// </summary>
        /// <param name="value">字符串</param>
        /// <returns>转换后的 <see cref="System.Int32"/></returns>
        public static int? ToInt32Nullable(this string value, NumberStyles style = NumberStyles.Any, IFormatProvider provider = null)
        {
            int temp;
            return int.TryParse(value, style, provider, out temp) ? (int?)temp : null;
        }

        #endregion ToInt32

        #region ToInt64

        /// <summary>
        /// 将字符串转换为Int值
        /// </summary>
        /// <param name="value">字符串</param>
        /// <param name="defaultValue">如果转换失败,则返回的默认值</param>
        /// <returns>转换后的 <see cref="System.Int64"/></returns>
        public static long ToInt64(this string value, long defaultValue = 0, NumberStyles style = NumberStyles.Any, IFormatProvider provider = null)
        {
            long temp;
            return long.TryParse(value, style, provider, out temp) ? temp : defaultValue;
        }

        /// <summary>
        /// 将字符串转换为Int值
        /// </summary>
        /// <param name="value">字符串</param>
        /// <returns>转换后的 <see cref="System.Int64"/></returns>
        public static long? ToInt64Nullable(this string value, NumberStyles style = NumberStyles.Any, IFormatProvider provider = null)
        {
            long temp;
            return long.TryParse(value, style, provider, out temp) ? (long?)temp : null;
        }

        #endregion ToInt64

        #region ToSingle

        /// <summary>
        /// 转换字符串为浮点数.如果转换失败,则返回指定的默认值
        /// </summary>
        /// <param name="value">要转换的字符串</param>
        /// <param name="defaultValue">如果转换失败,则返回的默认值</param>
        /// <returns>转换后的 <see cref="System.Single"/></returns>
        public static float ToSingle(this string value, float defaultValue = 0.0F, NumberStyles style = NumberStyles.Any, IFormatProvider provider = null)
        {
            float temp;
            return float.TryParse(value, style, provider, out temp) ? temp : defaultValue;
        }

        /// <summary>
        /// 转换字符串为浮点数.如果转换失败,则返回null
        /// </summary>
        /// <param name="value">要转换的字符串</param>
        /// <returns>转换后的 <see cref="System.Single"/></returns>
        public static float? ToSingleNullable(this string value, NumberStyles style = NumberStyles.Any, IFormatProvider provider = null)
        {
            float temp;
            return float.TryParse(value, style, provider, out temp) ? (float?)temp : null;
        }

        #endregion ToSingle

        #region ToDateTime

        /// <summary>
        /// 转换字符串为日期时间.如果转换失败,则返回指定的默认值
        /// </summary>
        /// <param name="value">要转换的字符串</param>
        /// <param name="defaultValue">如果转换失败,则返回的默认值</param>
        /// <param name="formatProvider">格式</param>
        /// <param name="styles"></param>
        /// <returns>
        /// 转换后的 <see cref="System.DateTime"/>
        /// </returns>
        public static DateTime ToDateTime(this string value, DateTime defaultValue, IFormatProvider formatProvider = null, DateTimeStyles styles = DateTimeStyles.None)
        {
            DateTime temp;
            return DateTime.TryParse(value, formatProvider, styles, out temp) ? temp : defaultValue;
        }

        /// <summary>
        /// 转换字符串为日期时间.如果转换失败,则返回指定的默认值
        /// </summary>
        /// <param name="value">要转换的字符串</param>
        /// <param name="defaultValue">如果转换失败,则返回的默认值</param>
        /// <returns>转换后的 <see cref="System.DateTime"/></returns>
        public static DateTime ToDateTimeExact(this string value, DateTime defaultValue, string format, IFormatProvider formatProvider = null, DateTimeStyles styles = DateTimeStyles.None)
        {
            DateTime temp;
            return DateTime.TryParseExact(value, format, formatProvider, styles, out temp) ? temp : defaultValue;
        }

        /// <summary>
        /// 转换字符串为日期时间.如果转换失败,则返回指定的默认值
        /// </summary>
        /// <param name="value">要转换的字符串</param>
        /// <param name="defaultValue">如果转换失败,则返回的默认值</param>
        /// <returns>转换后的 <see cref="System.DateTime"/></returns>
        public static DateTime ToDateTimeExact(this string value, DateTime defaultValue, string[] formats, IFormatProvider formatProvider = null, DateTimeStyles styles = DateTimeStyles.None)
        {
            DateTime temp;
            return DateTime.TryParseExact(value, formats, formatProvider, styles, out temp) ? temp : defaultValue;
        }

        /// <summary>
        /// 转换字符串为日期时间.如果转换失败,则返回指定的默认值
        /// </summary>
        /// <param name="value">要转换的字符串</param>
        /// <returns>转换后的 <see cref="System.DateTime"/></returns>
        public static DateTime ToDateTime(this string value, IFormatProvider formatProvider = null, DateTimeStyles styles = DateTimeStyles.None)
        {
            DateTime temp;
            return DateTime.TryParse(value, formatProvider, styles, out temp) ? temp : DateTime.MinValue;
        }

        /// <summary>
        /// 转换字符串为日期时间.如果转换失败,则返回指定的默认值
        /// </summary>
        /// <param name="value">要转换的字符串</param>
        /// <returns>转换后的 <see cref="System.DateTime"/></returns>
        public static DateTime ToDateTimeExact(this string value, string[] format = null, IFormatProvider formatProvider = null, DateTimeStyles styles = DateTimeStyles.None)
        {
            DateTime temp;
            return DateTime.TryParseExact(value, format, formatProvider, styles, out temp) ? temp : DateTime.MinValue;
        }

        /// <summary>
        /// 转换字符串为日期时间.如果转换失败,则返回 <see cref="F:System.DataTime.MinValue"/>
        /// </summary>
        /// <param name="value">要转换的字符串</param>
        /// <returns>转换后的 <see cref="System.DateTime"/></returns>
        public static DateTime ToDateTimeExact(this string value, string format, IFormatProvider formatProvider = null, DateTimeStyles styles = DateTimeStyles.None)
        {
            DateTime temp;
            return DateTime.TryParseExact(value, format, formatProvider, styles, out temp) ? temp : DateTime.MinValue;
        }

        /// <summary>
        /// 转换字符串为日期时间.如果转换失败,则返回null
        /// </summary>
        /// <param name="value">要转换的字符串</param>
        /// <returns>转换后的 <see cref="System.DateTime"/></returns>
        public static DateTime? ToDateTimeNullable(this string value, IFormatProvider formatProvider = null, DateTimeStyles styles = DateTimeStyles.None)
        {
            DateTime temp;
            return DateTime.TryParse(value, out temp) ? (DateTime?)temp : null;
        }

        /// <summary>
        /// 转换字符串为日期时间.如果转换失败,则返回null
        /// </summary>
        /// <param name="value">要转换的字符串</param>
        /// <returns>转换后的 <see cref="System.DateTime"/></returns>
        public static DateTime? ToDateTimeNullableExact(this string value, string format, IFormatProvider formatProvider = null, DateTimeStyles styles = DateTimeStyles.None)
        {
            DateTime temp;
            return DateTime.TryParseExact(value, format, formatProvider, styles, out temp) ? (DateTime?)temp : null;
        }

        /// <summary>
        /// 转换字符串为日期时间.如果转换失败,则返回null
        /// </summary>
        /// <param name="value">要转换的字符串</param>
        /// <returns>转换后的 <see cref="System.DateTime"/></returns>
        public static DateTime? ToDateTimeNullableExact(this string value, string[] formats, IFormatProvider formatProvider = null, DateTimeStyles styles = DateTimeStyles.None)
        {
            DateTime temp;
            return DateTime.TryParseExact(value, formats, formatProvider, styles, out temp) ? (DateTime?)temp : null;
        }

#if NET40

		/// <summary>
		/// 将字符串分析为可空Timespan
		/// </summary>
		/// <param name="value"></param>
		/// <returns></returns>
		public static TimeSpan? ToTimeSpanNullable(this string value, IFormatProvider formatProvider = null)
		{
			TimeSpan ts;
			if (TimeSpan.TryParse(value, formatProvider, out ts))
				return ts;

			return null;
		}

		/// <summary>
		/// 将字符串分析为可空Timespan
		/// </summary>
		/// <param name="value"></param>
		/// <returns></returns>
		public static TimeSpan? ToTimeSpanNullableExact(this string value, string format, IFormatProvider formatProvider = null, TimeSpanStyles styles = TimeSpanStyles.None)
		{
			TimeSpan ts;
			if (TimeSpan.TryParseExact(value, format, formatProvider, styles, out ts))
				return ts;

			return null;
		}

		/// <summary>
		/// 将字符串分析为可空Timespan
		/// </summary>
		/// <param name="value"></param>
		/// <returns></returns>
		public static TimeSpan? ToTimeSpanNullableExact(this string value, string[] format, IFormatProvider formatProvider = null, TimeSpanStyles styles = TimeSpanStyles.None)
		{
			TimeSpan ts;
			if (TimeSpan.TryParseExact(value, format, formatProvider, styles, out ts))
				return ts;

			return null;
		}

		/// <summary>
		/// 将字符串分析为Timespan
		/// </summary>
		/// <param name="value"></param>
		/// <returns></returns>
		public static TimeSpan ToTimeSpan(this string value, TimeSpan timeSpan, IFormatProvider formatProvider = null)
		{
			TimeSpan ts;
			if (TimeSpan.TryParse(value, formatProvider, out ts))
				return ts;

			return timeSpan;
		}

		/// <summary>
		/// 将字符串分析为Timespan
		/// </summary>
		/// <param name="value"></param>
		/// <returns></returns>
		public static TimeSpan ToTimeSpanExact(this string value, TimeSpan timeSpan, string format, IFormatProvider formatProvider = null, TimeSpanStyles styles = TimeSpanStyles.None)
		{
			TimeSpan ts;
			if (TimeSpan.TryParseExact(value, format, formatProvider, styles, out ts))
				return ts;

			return timeSpan;
		}

		/// <summary>
		/// 将字符串分析为Timespan
		/// </summary>
		/// <param name="value"></param>
		/// <returns></returns>
		public static TimeSpan ToTimeSpanExact(this string value, TimeSpan timeSpan, string[] format, IFormatProvider formatProvider = null, TimeSpanStyles styles = TimeSpanStyles.None)
		{
			TimeSpan ts;
			if (TimeSpan.TryParseExact(value, format, formatProvider, styles, out ts))
				return ts;

			return timeSpan;
		}

		/// <summary>
		/// 将字符串分析为Timespan
		/// </summary>
		/// <param name="value"></param>
		/// <returns></returns>
		public static TimeSpan ToTimeSpan(this string value, IFormatProvider formatProvider = null)
		{
			TimeSpan ts;
			if (TimeSpan.TryParse(value, formatProvider, out ts))
				return ts;

			return TimeSpan.Zero;
		}

		/// <summary>
		/// 将字符串分析为Timespan
		/// </summary>
		/// <param name="value"></param>
		/// <returns></returns>
		public static TimeSpan ToTimeSpanExact(this string value, string format, IFormatProvider formatProvider = null, TimeSpanStyles styles = TimeSpanStyles.None)
		{
			TimeSpan ts;
			if (TimeSpan.TryParseExact(value, format, formatProvider, styles, out ts))
				return ts;

			return TimeSpan.Zero;
		}

		/// <summary>
		/// 将字符串分析为Timespan
		/// </summary>
		/// <param name="value"></param>
		/// <returns></returns>
		public static TimeSpan ToTimeSpanExact(this string value, string[] format, IFormatProvider formatProvider = null, TimeSpanStyles styles = TimeSpanStyles.None)
		{
			TimeSpan ts;
			if (TimeSpan.TryParseExact(value, format, formatProvider, styles, out ts))
				return ts;

			return TimeSpan.Zero;
		}
#endif

        #endregion ToDateTime

        #region ToDouble

        /// <summary>
        /// 转换字符串为双精度数.如果转换失败,则返回 0.0
        /// </summary>
        /// <param name="value">要转换的字符串</param>
        /// <returns>转换后的 <see cref="System.Double"/></returns>
        public static double ToDouble(this string value, double defaultValue = 0.0, NumberStyles styles = NumberStyles.Any, IFormatProvider formatProvider = null)
        {
            double temp;
            return double.TryParse(value, styles, formatProvider, out temp) ? temp : 0.0;
        }

        /// <summary>
        /// 转换字符串为双精度数.如果转换失败,则返回指定的默认值
        /// </summary>
        /// <param name="value">要转换的字符串</param>
        /// <returns>转换后的 <see cref="System.Double"/></returns>
        public static double? ToDoubleNullable(this string value, NumberStyles styles = NumberStyles.Any, IFormatProvider formatProvider = null)
        {
            double temp;
            return double.TryParse(value, styles, formatProvider, out temp) ? (double?)temp : null;
        }

        #endregion ToDouble

        #region ToDecimal

        /// <summary>
        /// 转换字符串为双精度数.如果转换失败,则返回指定的默认值
        /// </summary>
        /// <param name="value">要转换的字符串</param>
        /// <param name="defaultValue">如果转换失败,则返回的默认值</param>
        /// <returns>转换后的 <see cref="System.Double"/></returns>
        public static decimal ToDecimal(this string value, decimal defaultValue = 0m, NumberStyles styles = NumberStyles.Any, IFormatProvider formatProvider = null)
        {
            decimal temp;
            return decimal.TryParse(value, styles, formatProvider, out temp) ? temp : defaultValue;
        }

        /// <summary>
        /// 转换字符串为双精度数.如果转换失败,则返回 0.0
        /// </summary>
        /// <param name="value">要转换的字符串</param>
        /// <returns>转换后的 <see cref="System.Double"/></returns>
        public static decimal? ToDecimalNullable(this string value, NumberStyles styles = NumberStyles.Any, IFormatProvider formatProvider = null)
        {
            decimal temp;
            return decimal.TryParse(value, styles, formatProvider, out temp) ? (decimal?)temp : null;
        }

        #endregion ToDecimal

        #region ToPoint

        /// <summary>
        /// 将字符串转换为坐标点格式
        /// </summary>
        /// <param name="location">字符串</param>
        /// <returns><see cref="T:System.Drawing.Point"/></returns>
        public static System.Drawing.Point ParseToPoint(this string location)
        {
            if (string.IsNullOrEmpty(location))
                return System.Drawing.Point.Empty;

            var pts = location.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            if (pts.Length < 2) return System.Drawing.Point.Empty;

            return new System.Drawing.Point(pts[0].ToInt32(), pts[1].ToInt32());
        }

        #endregion ToPoint

        #region ToGuid

        /// <summary>
        /// 	Convert the provided string to a Guid value.
        /// </summary>
        /// <param name = "value">The original string value.</param>
        /// <returns>The Guid</returns>
        public static Guid ToGuid(this string value)
        {
            return new Guid(value);
        }

        /// <summary>
        /// 	Convert the provided string to a Guid value and returns Guid.Empty if conversion fails.
        /// </summary>
        /// <param name = "value">The original string value.</param>
        /// <returns>The Guid</returns>
        public static Guid ToGuidSave(this string value)
        {
            return value.ToGuidSave(Guid.Empty);
        }

        /// <summary>
        /// 	Convert the provided string to a Guid value and returns the provided default value if the conversion fails.
        /// </summary>
        /// <param name = "value">The original string value.</param>
        /// <param name = "defaultValue">The default value.</param>
        /// <returns>The Guid</returns>
        public static Guid ToGuidSave(this string value, Guid defaultValue)
        {
            if (value.IsNullOrEmpty())
                return defaultValue;

            try
            {
                return value.ToGuid();
            }
            catch { }

            return defaultValue;
        }

        #endregion ToGuid

        #endregion Convert 转换

        #region Split 分隔

        #region 将文本内容字符串分割成行内容数组

        /// <summary>
        /// 将文本内容字符串分割成行内容数组
        /// </summary>
        /// <param name="sourceText"></param>
        /// <returns></returns>
        public static string[] ToLines(this string sourceText)
        {
            if (String.IsNullOrEmpty(sourceText))
                return null;
            return sourceText.Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
        }

        #endregion 将文本内容字符串分割成行内容数组

        #region 将字符串根据字符进行拆分成字符串数组，可设置成全部小写

        /// <summary>
        /// 返回的字符串数组包含此字符串中的子字符串（由指定 Unicode 字符数组的元素分隔）。参数指定要返回子字符串是否小写。
        /// </summary>
        /// <param name="source">要分隔的字符串。</param>
        /// <param name="speater">分隔此实例中子字符串的 Unicode 字符、不包含分隔符的空数组或 null。</param>
        /// <param name="toLower">要在分隔过程中转换为全小写，则为true,否则为false</param>
        /// <returns>一个数组，其元素包含此字符串中的子字符串，这些子字符串由 separator 中的一个或多个字符分隔。</returns>
        public static string[] ToStringArray(this string source, char speater, bool toLower)
        {
            string[] array = source.Split(speater);
            for (int i = 0; i < array.Length; i++)
            {
                if (!string.IsNullOrEmpty(array[i]) && array[i] != speater.ToString())
                {
                    string strVal = array[i];
                    if (toLower)
                    {
                        strVal = array[i].ToLower();
                    }
                    array[i] = strVal;
                }
            }
            return array;
        }

        #endregion 将字符串根据字符进行拆分成字符串数组，可设置成全部小写

        #region 将字符串根据开始标签与结束标签分割成字符串数组

        /// <summary>
        /// 按照标签分割并枚举
        /// </summary>
        /// <param name="text">文本</param>
        /// <param name="startTag">开始标签</param>
        /// <param name="endTag">结束标签</param>
        /// <param name="startPos">开始位置。默认为0</param>
        /// <returns>符合要求的代码片段</returns>
        public static IEnumerable<string> SplitByTag(this string text, string startTag, string endTag, int startPos = 0)
        {
            var index = 0;
            while ((index = text.IndexOf(startTag, startPos, StringComparison.OrdinalIgnoreCase)) != -1)
            {
                var endIndex = text.IndexOf(endTag, index + startTag.Length, StringComparison.OrdinalIgnoreCase);
                if (endIndex == -1) yield break;

                var str = text.Substring(index, endIndex - index + endTag.Length);
                startPos = endIndex + endTag.Length + 1;
                yield return str;
            }
        }

        #endregion 将字符串根据开始标签与结束标签分割成字符串数组

        #region 将字符串分割为整数数组

        private static char[] StringSpliter = new char[] { ',', '|', '\\', '/', ':', ';', '_', '#', '$', '%', '@', '!', '^', '&', '*' };

        /// <summary>
        /// 将字符串分割为整数数组
        /// </summary>
        /// <param name="source">要分割的字符串</param>
        /// <returns>返回最终的 <see cref="System.Int32"/>数组</returns>
        public static int[] SplitAsIntArray(this string source, string spliter = "", NumberStyles style = NumberStyles.Any, IFormatProvider provider = null)
        {
            if (string.IsNullOrEmpty(source)) return new int[0];
            if (string.IsNullOrEmpty(spliter))
            {
                return source.Split(StringSpliter, StringSplitOptions.RemoveEmptyEntries)
               .Select(s => s.ToInt32(style: style, provider: provider)).ToArray();
            }
            else
            {
                return source.Split(new string[] { spliter }, StringSplitOptions.RemoveEmptyEntries)
              .Select(s => s.ToInt32(style: style, provider: provider)).ToArray();
            }
        }

        /// <summary>
        /// 将字符串数组string[]转换成整数数组Int[]
        /// </summary>
        /// <param name="source"></param>
        /// <param name="style"></param>
        /// <param name="provider"></param>
        /// <returns></returns>
        public static int[] ToIntArray(this string[] sourceArray, NumberStyles style = NumberStyles.Any, IFormatProvider provider = null)
        {
            return Array.ConvertAll<string, int>(sourceArray, s => s.ToInt32(style: style, provider: provider));
        }

        #endregion 将字符串分割为整数数组

        #endregion Split 分隔

        #region Replace 替换

        /// <summary>
        /// 替换模板中目标字符
        /// </summary>
        /// <param name="template">模板内容</param>
        /// <param name="targetLabels">目标标签数组</param>
        /// <param name="replaceLabels">替换标签数组</param>
        /// <returns>替换后的结果</returns>
        public static string TemplateTagReplace(this string template, string[] targetLabels, string[] replaceLabels)
        {
            if (targetLabels.Length != replaceLabels.Length) throw new InvalidOperationException("数组长度必须一样.");

            for (int i = 0; i < targetLabels.Length; i++)
            {
                template = template.Replace(targetLabels[i], replaceLabels[i]);
            }
            return template;
        }

        /// <summary>
        /// 根据索引替换字符
        /// <para>eg:Assert.AreEqual("ZBCDEFGHIJ", StringHelper.ReplaceAt("ABCDEFGHIJ",0,'Z'));</para>
        /// </summary>
        /// <param name="data">需要操作的字符串</param>
        /// <param name="index">目标索引</param>
        /// <param name="replace">替换成字符</param>
        /// <returns>操作后的字符串</returns>
        public static string ReplaceAt(this string data, int index, char replace)
        {
            StringBuilder _builder = new StringBuilder(data);
            _builder[index] = replace;
            return _builder.ToString();
        }

        /// <summary>
        /// 根据索引替换字符串
        /// <para>eg:Assert.AreEqual("ZXCDEFGHIJ", StringHelper.ReplaceAt("ABCDEFGHIJ", 0, 2, "ZX"));</para>
        /// </summary>
        /// <param name="data">需要操作的字符串</param>
        /// <param name="index">目标索引</param>
        /// <param name="length">需要替换长度</param>
        /// <param name="replace">替换成字符串</param>
        /// <returns>操作后的字符串</returns>
        public static string ReplaceAt(this string data, int index, int length, string replace)
        {
            StringBuilder _builder = new StringBuilder(data);
            _builder.Remove(index, length);
            _builder.Insert(index, replace);
            return _builder.ToString();
        }

        #endregion Replace 替换

        #region Compare 比较

        /// <summary>
        /// 比较两个字符串在忽略大小写的情况下是否相等
        /// </summary>
        /// <param name="value">字符串1</param>
        /// <param name="compareTo">要比较的字符串</param>
        /// <returns>是否相等</returns>
        public static bool IsIgnoreCaseEqualTo(this string value, string compareTo)
        {
            return string.Compare(value, compareTo, true) == 0;
        }

        #endregion Compare 比较

        #region Format 格式化

        /// <summary>
        /// 将指定字符串中的格式项替换为指定数组中相应对象的字符串表示形式。
        /// </summary>
        /// <param name="format">The value.</param>
        /// <param name="args">The args.</param>
        /// <returns></returns>
        [StringFormatMethod("value")]
        public static string FormatWith(this string format, params object[] args)
        {
            if (format == null) throw new ArgumentNullException("value");
            else if (format.Length == 0) return string.Empty;
            else if (args.Length == 0) return format;
            else return string.Format(format, args);
        }

        /// <summary>
        /// 	Trims the text to a provided maximum length.
        /// </summary>
        /// <param name = "value">The input string.</param>
        /// <param name = "maxLength">Maximum length.</param>
        /// <returns></returns>
        /// <remarks>
        /// 	Proposed by Rene Schulte
        /// </remarks>
        public static string TrimToMaxLength(this string value, int maxLength)
        {
            return (value == null || value.Length <= maxLength ? value : value.Substring(0, maxLength));
        }

        /// <summary>
        /// 	Trims the text to a provided maximum length and adds a suffix if required.
        /// </summary>
        /// <param name = "value">The input string.</param>
        /// <param name = "maxLength">Maximum length.</param>
        /// <param name = "suffix">The suffix.</param>
        /// <returns></returns>
        /// <remarks>
        /// 	Proposed by Rene Schulte
        /// </remarks>
        public static string TrimToMaxLength(this string value, int maxLength, string suffix)
        {
            return (value == null || value.Length <= maxLength ? value : string.Concat(value.Substring(0, maxLength), suffix));
        }

        #endregion Format 格式化

        #region Insert 插入

        /// <summary>
        /// 文字换行,在字符串中插入'\r\n'字符
        /// <para>eg:StringHelper.WrapText("YanZhiwei", 3);==>"Yan\r\nZhi\r\nwei"</para>
        /// </summary>
        /// <param name="data">需要换行的文字</param>
        /// <param name="maxWidth">多少长度换行</param>
        /// <returns>换行好的文字</returns>
        public static string WrapText(this string data, int maxWidth)
        {
            int _stringCount = data.Length;
            if (maxWidth > 0 && _stringCount > maxWidth)
            {
                StringBuilder _builderString = new StringBuilder(data);
                int _breakCount = _builderString.Length / maxWidth;
                for (int i = 0; i < _breakCount; i++)
                {
                    int _insertPosition = i * maxWidth;
                    if (_insertPosition != 0)
                    {
                        int _offset = (i - 1) * 2;//(\r\n)
                        _builderString.Insert(_insertPosition + _offset, Environment.NewLine);
                    }
                }
                return _builderString.ToString();
            }
            else
            {
                return data;
            }
        }

        #endregion Insert 插入

        #region Concat 拼接

        /// <summary>
        ///     返回一个以特定前缀开始的字符串
        /// 	Ensures that a string starts with a given prefix.
        /// </summary>
        /// <param name = "source">The string value to check.</param>
        /// <param name = "prefix">The prefix value to check for.</param>
        /// <returns>The string value including the prefix</returns>
        /// <example>
        /// 	<code>
        /// 		var extension = "txt";
        /// 		var fileName = string.Concat(file.Name, extension.EnsureStartsWith("."));
        /// 	</code>
        /// </example>
        public static string EnsurePrepend(this string source, string prefix)
        {
            return source.StartsWith(prefix) ? source : string.Concat(prefix, source);
        }

        /// <summary>
        /// 	Returns a combined value of strings from a string array
        /// </summary>
        /// <param name = "values">The values.</param>
        /// <param name = "prefix">The prefix.</param>
        /// <param name = "suffix">The suffix.</param>
        /// <param name = "quotation">The quotation (or null).</param>
        /// <param name = "separator">The separator.</param>
        /// <returns>
        /// 	A <see cref = "System.String" /> that represents this instance.
        /// </returns>
        /// <remarks>
        /// 	Contributed by blaumeister, http://www.codeplex.com/site/users/view/blaumeiser
        /// </remarks>
        public static string ToString(this string[] values, string prefix = "(", string suffix = ")", string quotation = "\"", string separator = ",")
        {
            var sb = new StringBuilder();
            sb.Append(prefix);

            for (var i = 0; i < values.Length; i++)
            {
                if (i > 0)
                    sb.Append(separator);
                if (quotation != null)
                    sb.Append(quotation);
                sb.Append(values[i]);
                if (quotation != null)
                    sb.Append(quotation);
            }

            sb.Append(suffix);
            return sb.ToString();
        }

        #endregion Concat 拼接

        #region SubString 截取

        /// <summary>
        /// 按照字节截取字符串
        /// </summary>
        /// <param name="value">字符串</param>
        /// <param name="byteLength">字节长度，一个汉字两个字节</param>
        /// <returns>截取后的字符串</returns>
        /// <exception cref="System.ArgumentException">指定了截取后的省略字符串，但要截取的字符串过短，不足以容纳省略字符串</exception>
        public static string GetSubString(this string value, int byteLength)
        {
            return GetSubString(value, byteLength, string.Empty);
        }

        /// <summary>
        /// 按照字节截取字符串
        /// </summary>
        /// <param name="value">字符串</param>
        /// <param name="byteLength">字节长度，一个汉字两个字节</param>
        /// <param name="tailString">如果截取了，那么省略字符串</param>
        /// <returns>截取后的字符串</returns>
        /// <exception cref="System.ArgumentException">指定了截取后的省略字符串，但要截取的字符串过短，不足以容纳省略字符串</exception>
        public static string GetSubString(this string value, int byteLength, string tailString)
        {
            if (value.IsNullOrEmpty()) return value;
            tailString = tailString ?? "";
            var tailLength = tailString.Select(s => (int)s > 255 ? 2 : 1).Sum();

            if (tailLength > 0) byteLength -= tailLength;
            if (byteLength < 1) throw new ArgumentException(ExtensionResources.StringExtract_GetSubString_LengthError);

            var currentLength = 0;
            var wordPosition = 0;
            while (currentLength < byteLength && wordPosition < value.Length) currentLength += value[wordPosition++] > 255 ? 2 : 1;
            if (wordPosition == value.Length) return value;
            else return value.Substring(0, wordPosition) + tailString;
        }

        /// <summary>
        /// 在字符串中搜索指定的特征字符串并截取其中的一段。
        /// </summary>
        /// <param name="source">源字符串</param>
        /// <param name="beginTag">开始特征字符串</param>
        /// <param name="endTag">结束特征字符串</param>
        /// <param name="beginIndex">开始索引</param>
        /// <param name="comparison">比较类型</param>
        /// <returns></returns>
        public static string SearchStringTag(this string source, string beginTag, string endTag, int beginIndex = 0, StringComparison comparison = StringComparison.OrdinalIgnoreCase)
        {
            return SearchStringTag(source, beginTag, endTag, ref beginIndex, comparison);
        }

        /// <summary>
        /// 在字符串中搜索指定的特征字符串并截取其中的一段。
        /// </summary>
        /// <param name="text">源字符串</param>
        /// <param name="beginTag">开始特征字符串</param>
        /// <param name="endTag">结束特征字符串</param>
        /// <param name="beginIndex">开始索引</param>
        /// <param name="comparison">比较类型</param>
        /// <returns></returns>
        public static string SearchStringTag(this string text, string beginTag, string endTag, ref int beginIndex, StringComparison comparison = StringComparison.OrdinalIgnoreCase)
        {
            if (string.IsNullOrEmpty(text) || beginIndex >= text.Length)
                return string.Empty;

            var startIndex = beginIndex;
            var endIndex = text.Length;

            if (!string.IsNullOrEmpty(beginTag))
                //从开始位置查找索引
                startIndex = text.IndexOf(beginTag, startIndex, comparison);
            if (startIndex == -1)
                return string.Empty;

            if (!string.IsNullOrEmpty(endTag))
                endIndex = text.IndexOf(endTag, startIndex + (!string.IsNullOrEmpty(beginTag) ? beginTag.Length : 1), comparison);
            if (endIndex == -1)
                return string.Empty;

            beginIndex = endIndex + (!string.IsNullOrEmpty(endTag) ? endTag.Length : 1);

            return text.Substring(startIndex, endIndex - startIndex + (string.IsNullOrEmpty(endTag) ? 0 : endTag.Length));
        }

        #endregion SubString 截取

        #region Count 计数

        /// <summary>
        /// 获得指定字符串的字节长度
        /// </summary>
        /// <param name="value">值</param>
        /// <returns><see cref="T:System.Int32"/></returns>
        public static int GetByteCount(this string value)
        {
            return GetByteCount(value, Encoding.Unicode);
        }

        /// <summary>
        /// 获得指定字符串的字节长度
        /// </summary>
        /// <param name="value">值</param>
        /// <param name="encoding">编码</param>
        /// <returns><see cref="T:System.Int32"/></returns>
        public static int GetByteCount(this string value, Encoding encoding)
        {
            if (value.IsNullOrEmpty()) return 0;
            return encoding.GetByteCount(value);
        }

        #endregion Count 计数

    }
}